/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.octopeer.message;

import java.io.File;
import java.io.StringReader;

import java.util.ArrayList;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import net.octopeer.core.Peer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import org.xml.sax.InputSource;

import net.octopeer.core.PeerNode;
import net.octopeer.core.Resource;
import net.octopeer.utilities.XMLTools;
import net.octopeer.utilities.SimpleSHA1;

/**
 *
 * @author andria
 */
public class Announcement {
    private PeerNode peer;
    private ArrayList<Resource> resourceList;
    
    public Announcement() {
        this.peer = null;
        this.resourceList = new ArrayList<Resource>();
    }
    
    public Announcement(PeerNode peer, ArrayList<Resource> resourceList) {
        this.peer = peer;
        this.resourceList = resourceList;
    }
    
//    public Announcement(PeerNode peerHost, Resource resource) {
//        this.peer = peerHost;
//        this.resourceList = new ArrayList<Resource>();
//        this.resourceList.add(resource);
//    }
    
    public void setPeer(PeerNode peer) {
        this.peer = peer;
    }
    
    public void setResourceList(ArrayList<Resource> resourceList) {
        this.resourceList = resourceList;
    } 
    
    public void addResource(Resource resource) {
        this.resourceList.add(resource);
    }
    
    public PeerNode getPeerHost() {
        return this.peer;
    }
    
    public ArrayList<Resource> resourceList() {
        return this.resourceList;
    }
    
    public Document toXMLDoc() throws Exception {
        Document doc;
        XMLTools xt = new XMLTools();        
        doc = xt.db.newDocument();
        
        Element rootEle = doc.createElement("Announcement");

        // Peer
        Element peerNodeEle = doc.createElement("Announcement:Peer");
        
            // ID
            Element peerNodeIDEle = doc.createElement("Announcement:Peer:ID");
            Text peerNodeIDText = doc.createTextNode(this.peer.getNodeID());
            peerNodeIDEle.appendChild(peerNodeIDText);
            peerNodeEle.appendChild(peerNodeIDEle);        

            // IPaddress
            Element peerNodeIPaddressEle = doc.createElement("Announcement:Peer:IPaddress");
            Text peerNodeIPaddressText = doc.createTextNode(this.peer.getNodeIPaddress());
            peerNodeIPaddressEle.appendChild(peerNodeIPaddressText);
            peerNodeEle.appendChild(peerNodeIPaddressEle);        

            // Port
            Element peerNodePortEle = doc.createElement("Announcement:Peer:Port");
            Text peerNodePortText = doc.createTextNode(Integer.toString(this.peer.getNodePort()));
            peerNodePortEle.appendChild(peerNodePortText);
            peerNodeEle.appendChild(peerNodePortEle);

        rootEle.appendChild(peerNodeEle);       
        
        // ResourceList
        Element peerResourceListEle = doc.createElement("Announcement:ResourceList");
        
            int peerResourceLoop = 0;
            while (peerResourceLoop < this.resourceList.size()) {
                Resource peerResource = (Resource) this.resourceList.get(peerResourceLoop);
                
                Element peerResourceEle = doc.createElement("Announcement:ResourceList:Resource");
                // ID
                Element peerResourceIDEle = doc.createElement("Announcement:ResourceList:ID");
                Text peerResourceIDText = doc.createTextNode(peerResource.getResourceID());
                peerResourceIDEle.appendChild(peerResourceIDText);
                peerResourceEle.appendChild(peerResourceIDEle);        

                // Type
                Element peerResourceTypeEle = doc.createElement("Announcement:ResourceList:Type");
                Text peerResourceTypeText = doc.createTextNode(peerResource.getResourceType());
                peerResourceTypeEle.appendChild(peerResourceTypeText);
                peerResourceEle.appendChild(peerResourceTypeEle);        

                // Detail
                Element peerResourceDetailEle = doc.createElement("Announcement:ResourceList:Detail");
                Text peerResourceDetailText = doc.createTextNode(peerResource.getResourceDetail());
                peerResourceDetailEle.appendChild(peerResourceDetailText);
                peerResourceEle.appendChild(peerResourceDetailEle);  

                peerResourceListEle.appendChild(peerResourceEle);
                
                peerResourceLoop++;
            }
        
        rootEle.appendChild(peerResourceListEle);
        
        doc.appendChild(rootEle);                
        
        return doc;
    }
    
    public String toXMLString() throws Exception {
        String result = null;
        
        XMLTools xt = new XMLTools();                
        result = xt.writeXMLString(this.toXMLDoc());
        
        return result;
    }
    
    public void toXMLFile(String fileName) throws Exception {
        // Prepare the DOM document for writing
        Source source = new DOMSource(this.toXMLDoc());

        // Prepare the output file
        File file = new File(fileName);
        Result result = new StreamResult(file);

        // Write the DOM document to the file
        Transformer xformer = TransformerFactory.newInstance().newTransformer();
        xformer.transform(source, result);
    }
    
    public Announcement fromXMLDoc(Document dom) {
        Announcement result = new Announcement();
        
        Element rootEle = dom.getDocumentElement();
        
        if (rootEle.getTagName().equals("Announcement")) {
            // Peer
            PeerNode peerNode = new PeerNode();
            NodeList peerNodeIDList = rootEle.getElementsByTagName("Announcement:Peer:ID");
            String peerNodeIDText = peerNodeIDList.item(0).getFirstChild().getNodeValue();
            NodeList peerNodeIPaddressList = rootEle.getElementsByTagName("Announcement:Peer:IPaddress");
            String peerNodeIPaddressText = peerNodeIPaddressList.item(0).getFirstChild().getNodeValue();
            NodeList peerNodePortList = rootEle.getElementsByTagName("Announcement:Peer:Port");
            String peerNodePortText = peerNodePortList.item(0).getFirstChild().getNodeValue();
            peerNode.setNodeID(peerNodeIDText);
            peerNode.setNodeIPaddress(peerNodeIPaddressText);
            peerNode.setNodePort(Integer.valueOf(peerNodePortText));
            
            result.setPeer(peerNode);
            
            // ResourceList
            NodeList peerResourceListList = rootEle.getElementsByTagName("Announcement:ResourceList");
            NodeList peerResourceList = rootEle.getElementsByTagName("Announcement:ResourceList:Resource");

            int peerResourceLoop = 0;
            
            while (peerResourceLoop < peerResourceList.getLength()) {
                NodeList peerResourceListEle = peerResourceList.item(peerResourceLoop).getChildNodes();
                
                Resource peerResource = new Resource();
                
                String resourceIDText = peerResourceListEle.item(0).getFirstChild().getNodeValue();
                String resourceTypeText = peerResourceListEle.item(1).getFirstChild().getNodeValue();
                String resourceDetailText = peerResourceListEle.item(2).getFirstChild().getNodeValue();

                peerResource.setResourceID(resourceIDText);
                peerResource.setResourceType(resourceTypeText);
                peerResource.setResourceDetail(resourceDetailText);

                result.resourceList.add(peerResource);
                
                peerResourceLoop++;
            }
    
        }
                
        return result;
    }
    
    public Announcement fromXMLString(String data) throws Exception {
        Document dom = null;
        XMLTools xt = new XMLTools();
        Announcement result = null;
        
        // Parse the XML stream input to Document type
        dom = xt.db.parse(new InputSource(new StringReader(data)));
        
        result = fromXMLDoc(dom);
        
        return result;
    }
    
    public Announcement fromXMLFile(String fileName) throws Exception {
        Document dom = null;
        File file = null;
        Announcement result = null;
        XMLTools xt = new XMLTools();
        
        // Parse the XML stream input to Document type
        file = new File(fileName);
        dom = xt.db.parse(file);
        
        result = fromXMLDoc(dom);
        
        return result;
    }
    
//    public static void main(String[] args) throws Exception {
////        Peer peer = new Peer();
////        peer = peer.fromXMLFile("./conf/peer1.xml");
////        
////        Announcement anno = new Announcement(peer.getNode(), peer.getResourceList());
////        anno.toXMLFile("./conf/anno1.xml");
//        Announcement anno = new Announcement();
//        anno = anno.fromXMLFile("./conf/anno1.xml");
//        
//        anno.toXMLFile("./conf/anno2.xml");
//    }
}
